iT邦幫忙

2025 iThome 鐵人賽

DAY 25
0
自我挑戰組

30天用Python打造你的數位金融實力:從零開始的FinTech入門筆記系列 第 25

用 Python 每週產生消費摘要並自動寄信

  • 分享至 

  • xImage
  •  

目前我們已經會記帳、分類、畫圖了。下一步是讓「報表自動到手」,把理財養成習慣 — 我們今天做一個 每週消費摘要自動器:它會讀 expense.csv(找不到就自動建立示範)、產生「分類總額」的長條圖與 CSV 摘要,並嘗試把報告寄到你的 Email(若你提供環境變數憑證)。整個流程簡單、安全(鼓勵用環境變數),非常適合拿來展示「把資料流程自動化」的能力。

為什麼重要?

  • 自動化是 FinTech 的核心能力:把人工流程(抓資料、整理、發報告)變成可重複的機器工作。
  • 這個作品能直接放 GitHub、放在面試作品中演示「每日/每週自動報表」的能力。
  • 對新手友好:程式碼不複雜,但涵蓋 I/O、簡單圖表、檔案產生與(選擇性)郵件寄送。

Python 小實作

import os
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
import smtplib, ssl
from email.message import EmailMessage

plt.rcParams['font.family'] = 'Heiti TC'

CSV_PATH = "expense.csv"
OUT_PNG = "weekly_category.png"
OUT_CSV = "weekly_summary.csv"

# 1) 若沒有 expense.csv,就建立示範資料
if not os.path.exists(CSV_PATH):
    demo = pd.DataFrame({
        "日期": ["2025-08-01","2025-08-02","2025-08-03","2025-08-06","2025-08-07","2025-08-08","2025-08-09"],
        "類別": ["早餐","午餐","購物","交通","晚餐","咖啡","購物"],
        "金額": [60,120,900,35,200,75,450]
    })
    demo.to_csv(CSV_PATH, index=False)
    print("已建立示範 expense.csv")

# 2) 讀檔、轉型與取過去 7 天資料
df = pd.read_csv(CSV_PATH)
df['日期'] = pd.to_datetime(df['日期'], errors='coerce')
today = pd.Timestamp.now().normalize()
one_week_ago = today - pd.Timedelta(days=7)
recent = df[df['日期'] >= one_week_ago]

if recent.empty:
    print("過去 7 天沒有資料,將以全部資料為基礎。")
    recent = df.copy()

# 3) 分類加總並存檔
summary = recent.groupby('類別')['金額'].sum().sort_values(ascending=False)
summary_df = summary.reset_index().rename(columns={'金額':'總支出'})
summary_df.to_csv(OUT_CSV, index=False)
print(f"已輸出每週摘要:{OUT_CSV}")

# 4) 畫圖並存檔
plt.figure(figsize=(6,4))
summary.plot(kind='bar')
plt.title("過去 7 天各類別支出")
plt.xlabel("類別")
plt.ylabel("金額(元)")
plt.tight_layout()
plt.savefig(OUT_PNG)
plt.close()
print(f"已輸出圖檔:{OUT_PNG}")

# 5) 選擇性:把報表寄到 Email(若你不想寄,程式會跳過)
EMAIL_USER = os.getenv("REPORT_EMAIL_USER")
EMAIL_PASS = os.getenv("REPORT_EMAIL_PASS")  # 建議使用 App Password,且不要硬寫在程式

if EMAIL_USER and EMAIL_PASS:
    recipient = EMAIL_USER  # 自寄檢查;可改成其他收件人
    msg = EmailMessage()
    msg["Subject"] = f"每週消費摘要 ({today.date()})"
    msg["From"] = EMAIL_USER
    msg["To"] = recipient
    body = f"這是自動產生的每週消費摘要,請見附件({OUT_CSV}, {OUT_PNG})。"
    msg.set_content(body)

    # attach CSV
    with open(OUT_CSV, "rb") as f:
        msg.add_attachment(f.read(), maintype="text", subtype="csv", filename=OUT_CSV)
    # attach image
    with open(OUT_PNG, "rb") as f:
        msg.add_attachment(f.read(), maintype="image", subtype="png", filename=OUT_PNG)

    # 使用 Gmail SMTP 範例(必要時改成你的 SMTP)
    try:
        context = ssl.create_default_context()
        with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as server:
            server.login(EMAIL_USER, EMAIL_PASS)
            server.send_message(msg)
        print("✅ 每週摘要已成功寄出(寄到自己的信箱)")
    except Exception as e:
        print("寄件失敗:", e)
        print("你可以把檔案手動附上寄出,或檢查 SMTP 設定與帳密。")
else:
    print("未設定郵件環境變數,已產生檔案,可手動寄出或設定後自動寄送。")

小提醒

  1. 如果要自動寄 Gmail,需開啟兩步驟驗證並用「App 密碼」,不要把帳密寫死在程式。
  2. 如果你在 Windows 或 Colab 執行,CSV 路徑與相對路徑要注意工作目錄。

上一篇
健康保險 × 風險因子:用 BMI 做保費等級模擬
下一篇
永續金融入門:用 Python 模擬 ESG 投資績效
系列文
30天用Python打造你的數位金融實力:從零開始的FinTech入門筆記29
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言